

package net.qiqbframework.spring.config;


import net.qiqbframework.messaging.annotation.ClasspathParameterResolverFactory;
import net.qiqbframework.messaging.annotation.MultiParameterResolverFactory;
import net.qiqbframework.messaging.annotation.HandlerParameterResolverFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;

public class SpringParameterResolverFactoryBean implements FactoryBean<HandlerParameterResolverFactory>,
        BeanClassLoaderAware, InitializingBean, ApplicationContextAware {

    private final List<HandlerParameterResolverFactory> factories = new ArrayList<>();
    private ClassLoader classLoader;
    private ApplicationContext applicationContext;

    @Override
    public HandlerParameterResolverFactory getObject() {
        return MultiParameterResolverFactory.ordered(factories);
    }

    @Override
    public Class<?> getObjectType() {
        return HandlerParameterResolverFactory.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public void afterPropertiesSet() {
        factories.add(ClasspathParameterResolverFactory.forClassLoader(classLoader));
        factories.add(new SpringBeanDependencyResolverFactory(applicationContext));
        factories.add(new SpringBeanParameterResolverFactory(applicationContext));
    }

    /**
     * Defines any additional parameter resolver factories that need to be used to resolve parameters. By default, the
     * ParameterResolverFactories found on the classpath, as well as a SpringBeanParameterResolverFactory are
     * registered.
     *
     * @param additionalFactories The extra factories to register
     * @see SpringBeanParameterResolverFactory
     * @see SpringBeanDependencyResolverFactory
     * @see ClasspathParameterResolverFactory
     */
    public void setAdditionalFactories(List<HandlerParameterResolverFactory> additionalFactories) {
        this.factories.addAll(additionalFactories);
    }

    @Override
    public void setBeanClassLoader(@Nonnull ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    @Override
    public void setApplicationContext(@Nonnull ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
